package com.carryking.smart.rpc.proxy;

import com.carryking.smart.rpc.constant.RespStatusConstant;
import com.carryking.smart.rpc.discover.DiscoverService;
import com.carryking.smart.rpc.discover.DiscoverServiceFactory;
import com.carryking.smart.rpc.entity.RequestEntity;
import com.carryking.smart.rpc.entity.ResponseEntity;
import com.carryking.smart.rpc.entity.ServiceInfoEntity;
import com.carryking.smart.rpc.utils.RequestUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomUtils;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * Created by jincarry on 2018/1/11.
 */
@Slf4j
public class ClientServiceInvokeHandler implements InvocationHandler {

    private DiscoverService discoverService = DiscoverServiceFactory.build();

    private int timeOut;

    public ClientServiceInvokeHandler(int timeOut) {
        this.timeOut = timeOut;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        RequestEntity requestEntity = new RequestEntity();
        String className = method.getDeclaringClass().getName();
        requestEntity.setClassName(className);
        requestEntity.setMethodName(method.getName());
        requestEntity.setParamsClass(method.getParameterTypes());
        requestEntity.setParams(args);
        requestEntity.setRequestId(RandomUtils.nextLong());

        String serviceName = method.getDeclaringClass().getSimpleName();

        ServiceInfoEntity serviceInfoEntity = discoverService.getServiceInfoByName(serviceName);
        if (serviceInfoEntity == null) {
            log.error("远程服务调用失败,service不存在,serviceName={}",serviceName);
            ResponseEntity responseEntity = new ResponseEntity();
            responseEntity.setRequestId(requestEntity.getRequestId());
            responseEntity.setCode(RespStatusConstant.TIME_OUT);
            return responseEntity;
        }
        ResponseEntity responseEntity = RequestUtils.send(serviceInfoEntity.getIp(),serviceInfoEntity.getPort(),timeOut, requestEntity);
        return responseEntity.getRespBody();
    }
}
